package com.obggtc.picture.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * JWT Token缓存工具类
 */
@Component
public class JwtCacheUtils {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private JwtUtils jwtUtils;

    // Redis Key前缀
    private static final String TOKEN_BLACKLIST_PREFIX = "jwt:blacklist:";
    private static final String TOKEN_INFO_PREFIX = "jwt:info:";
    private static final String USER_TOKEN_PREFIX = "jwt:user:";
    private static final String REFRESH_TOKEN_PREFIX = "jwt:refresh:";

    /**
     * 将token加入黑名单
     * @param token JWT token
     * @param expireTime 过期时间（秒）
     */
    public void addToBlacklist(String token, long expireTime) {
        String key = TOKEN_BLACKLIST_PREFIX + token;
        redisUtils.set(key, "blacklisted", expireTime);
    }

    /**
     * 检查token是否在黑名单中
     * @param token JWT token
     * @return true: 在黑名单中, false: 不在黑名单中
     */
    public boolean isInBlacklist(String token) {
        String key = TOKEN_BLACKLIST_PREFIX + token;
        return redisUtils.hasKey(key);
    }

    /**
     * 缓存token信息
     * @param token JWT token
     * @param username 用户名
     * @param expireTime 过期时间（秒）
     */
    public void cacheTokenInfo(String token, String username, long expireTime) {
        String key = TOKEN_INFO_PREFIX + token;
        redisUtils.set(key, username, expireTime);
    }

    /**
     * 从缓存中获取token对应的用户名
     * @param token JWT token
     * @return 用户名
     */
    public String getUsernameFromCache(String token) {
        String key = TOKEN_INFO_PREFIX + token;
        Object username = redisUtils.get(key);
        return username != null ? username.toString() : null;
    }

    /**
     * 缓存用户当前活跃的token
     * @param username 用户名
     * @param token JWT token
     * @param expireTime 过期时间（秒）
     */
    public void cacheUserToken(String username, String token, long expireTime) {
        String key = USER_TOKEN_PREFIX + username;
        redisUtils.set(key, token, expireTime);
    }

    /**
     * 获取用户当前活跃的token
     * @param username 用户名
     * @return JWT token
     */
    public String getUserActiveToken(String username) {
        String key = USER_TOKEN_PREFIX + username;
        Object token = redisUtils.get(key);
        return token != null ? token.toString() : null;
    }

    /**
     * 用户登出，清除所有相关缓存
     * @param token JWT token
     * @param username 用户名
     */
    public void logout(String token, String username) {
        // 1. 将token加入黑名单
        try {
            long remainingTime = jwtUtils.getExpire(token);
            if (remainingTime > 0) {
                addToBlacklist(token, remainingTime);
            }
        } catch (Exception e) {
            // token可能已过期，设置一个短暂的黑名单时间
            addToBlacklist(token, 300); // 5分钟
        }

        // 2. 清除token信息缓存
        String tokenInfoKey = TOKEN_INFO_PREFIX + token;
        redisUtils.del(tokenInfoKey);

        // 3. 清除用户活跃token缓存
        String userTokenKey = USER_TOKEN_PREFIX + username;
        redisUtils.del(userTokenKey);

        // 4. 清除刷新token缓存
        String refreshTokenKey = REFRESH_TOKEN_PREFIX + username;
        redisUtils.del(refreshTokenKey);
    }

    /**
     * 强制用户下线（踢出用户）
     * @param username 用户名
     */
    public void forceLogout(String username) {
        // 获取用户当前活跃的token
        String activeToken = getUserActiveToken(username);
        if (activeToken != null) {
            logout(activeToken, username);
        }
    }

    /**
     * 缓存刷新token
     * @param username 用户名
     * @param refreshToken 刷新token
     * @param expireTime 过期时间（秒）
     */
    public void cacheRefreshToken(String username, String refreshToken, long expireTime) {
        String key = REFRESH_TOKEN_PREFIX + username;
        redisUtils.set(key, refreshToken, expireTime);
    }

    /**
     * 获取用户的刷新token
     * @param username 用户名
     * @return 刷新token
     */
    public String getRefreshToken(String username) {
        String key = REFRESH_TOKEN_PREFIX + username;
        Object token = redisUtils.get(key);
        return token != null ? token.toString() : null;
    }

    /**
     * 删除刷新token
     * @param username 用户名
     */
    public void removeRefreshToken(String username) {
        String key = REFRESH_TOKEN_PREFIX + username;
        redisUtils.del(key);
    }

    /**
     * 检查token是否有效（考虑黑名单）
     * @param token JWT token
     * @return true: 有效, false: 无效
     */
    public boolean isTokenValid(String token) {
        // 1. 检查是否在黑名单中
        if (isInBlacklist(token)) {
            return false;
        }

        // 2. 检查JWT本身是否有效
        return jwtUtils.validateToken(token) && !jwtUtils.isTokenExpired(token);
    }

    /**
     * 延长token有效期（通过缓存实现）
     * @param token JWT token
     * @param username 用户名
     * @param additionalTime 延长的时间（秒）
     */
    public void extendTokenValidity(String token, String username, long additionalTime) {
        // 更新token信息缓存的过期时间
        String tokenInfoKey = TOKEN_INFO_PREFIX + token;
        long currentExpire = redisUtils.getExpire(tokenInfoKey);
        if (currentExpire > 0) {
            redisUtils.expire(tokenInfoKey, currentExpire + additionalTime);
        }

        // 更新用户活跃token缓存的过期时间
        String userTokenKey = USER_TOKEN_PREFIX + username;
        long userTokenExpire = redisUtils.getExpire(userTokenKey);
        if (userTokenExpire > 0) {
            redisUtils.expire(userTokenKey, userTokenExpire + additionalTime);
        }
    }

    /**
     * 获取在线用户数量（基于活跃token缓存）
     * @return 在线用户数量
     */
    public long getOnlineUserCount() {
        // 这里简化实现，实际可以通过扫描USER_TOKEN_PREFIX前缀的key来统计
        // 由于Redis扫描可能影响性能，建议另外维护一个在线用户计数器
        return 0L; // 需要根据实际需求实现
    }

    /**
     * 清理过期的黑名单token（定时任务使用）
     */
    public void cleanExpiredBlacklistTokens() {
        // 这个方法可以在定时任务中调用，清理已过期的黑名单token
        // Redis会自动清理过期的key，所以这里主要是统计和日志记录
    }
} 